﻿using System.Collections.Generic;
using System.Linq;

namespace AutomatedDecisionMaking.Class.Algorithms
{
    class MOWmaxAlgorithm
    {
        private readonly DecisionMatrix _mDecisionMatrix;   /// Macierz decyzji
        private readonly List<double> _mWeightedValues;     /// Wartości po wymnożeniu przez wagi laplacea
        private readonly List<string> _mStrWeightedValues;  /// Wartości ważone dla poszczególnych wierszy w stringach
        private List<double> _mScenarioWeights;             /// Wagi poszczególnych scenariuszy
        private double _mMaxWeightedVal;                    /// Maksymalna wartość ważona
        private string _mDecision;                          /// Podjęta decyzja

        /// <summary>
        /// Konstruktor algorytmu realizującego kryterium największego oczekiwanego żalu.
        /// </summary>
        /// <param name="decisionMatrix">Macierz decyzji wprowadzona porzez użytkownika</param>
        public MOWmaxAlgorithm(DecisionMatrix decisionMatrix)
        {
            _mStrWeightedValues = new List<string>();
            _mWeightedValues = new List<double>();
            _mScenarioWeights = new List<double>();
            _mDecisionMatrix = decisionMatrix;
        }

        /// <summary>
        /// Reset całego algorytmu
        /// </summary>
        public void Reset()
        {
            _mStrWeightedValues.Clear();
            _mWeightedValues.Clear();
            _mScenarioWeights.Clear();
        }

        /// <summary>
        /// Uruchomienie algorytmu i rozwiązanie postawionego zadania
        /// </summary>
        public void CalculateSolution()
        {
            for (int i = 0; i < _mDecisionMatrix.DecisionList.Count; ++i)
            {
                string element = _mDecisionMatrix.DecisionList.ElementAt(i);
                double weightedVal = 0;
                var decisionRow = _mDecisionMatrix.Value[i];
                for (int j = 0; j < decisionRow.Count; ++j)
                    weightedVal += decisionRow[j]*_mScenarioWeights[j];


                _mStrWeightedValues.Add(element + " : wartość ważona = " + weightedVal);
                _mWeightedValues.Add(weightedVal);
            }

            _mMaxWeightedVal = _mWeightedValues.Max();
            _mDecision = _mDecisionMatrix.DecisionList.ElementAt(_mWeightedValues.FindIndex(w => w == _mMaxWeightedVal));
        }

        /// <summary>
        /// Dostęp do macierzy decyzji
        /// </summary>
        /// <returns>Macierz decyzji</returns>
        public DecisionMatrix GetDecisionMatrix()
        {
            return _mDecisionMatrix;
        }

        /// <summary>
        /// Dostęp do wag dla poszczególnych scenairuszy
        /// </summary>
        /// <returns>Wagi dla scenariuszy</returns>
        public List<double> GetWeights()
        {
            return _mScenarioWeights;
        }

        /// <summary>
        /// Ustawienie wag dla poszczególnych scenariuszy
        /// </summary>
        /// <param name="weights">Wagi dla scenariuszy</param>
        public void SetWeights(List<double> weights)
        {
            _mScenarioWeights = weights;
        }

        /// <summary>
        /// Dostęp do podjętej decyzji
        /// </summary>
        /// <returns>Podjęta decyzja</returns>
        public string GetDecision()
        {
            return _mDecision;
        }

        /// <summary>
        /// Dostęp do największej wartości ważonej
        /// </summary>
        /// <returns>Największa wartość ważona</returns>
        public double GetMaxWeightedValue()
        {
            return _mMaxWeightedVal;
        }

        /// <summary>
        /// Wartości ważone dla poszczególnych wierszy w formacie string
        /// </summary>
        /// <returns>Wartości ważone</returns>
        public List<string> GetWeightedValuesStr()
        {
            return _mStrWeightedValues;
        }

        /// <summary>
        /// Wartości ważone dla poszczególnych wierszy
        /// </summary>
        /// <returns>Wartości ważone</returns>
        public List<double> GetWeightedValues()
        {
            return _mWeightedValues;
        }
    }
}
